PROYECTO DE CLASE - ANÁLISIS DE SERIES DE TIEMPO
SERIE: ANÁLISIS DE COTIZACIONES EN BOLSA - ACCIONES DE ARGOS
Integrantes:
- Cesar Prieto
- Gabriel Peña
- Sebastian Gil
INTRODUCCION
La base de datos fue tomada de la pagina https://es.investing.com/equities/grupoargos-historical-data la cual proporciona estos datos de manera gratuita al publico, la inspiracion para desarrollar este trabajo con esta base es conocer como se comportan los metodos aprendidos en clase en un enfoque econocimo y sobre todo en el area de las acciones, con lo cual decidimos tomar los datos de un grupo empresarial Colombiano y realizar el analisis correspondiente para desarrollar el proyecto para la clase de series de tiempo.
Descripcion de la base:
- Acciones DIARIAS del Grupo ARGOS
- 3401 Datos tomado (Desde el 7/11/20114 Hasta 28/02/2024)
- Variables: Fecha, Último, Apertura, Máximo, Mínimo, Vol, %Var.
# Color2 <span style="color: #03396c;"></span>
DESARROLLO
IMPORTACION Y LIMPIEZA DE DATOS
Paquetes necesarios para el desarrollo del problema
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import statsmodels.api as sm
import plotly.express as px
from sklearn import __version__ as sklearn_version
from sklearn import *
# Ruta del archivo CSV
archivo_csv = r'C:\Users\HP\OneDrive\Documentos\DOCUMENTOS PERSONAJES\CESAR\Series\Pro_Series\Series-de-Tiempo\Datos\G_ARGOS.csv'
# Cargar el archivo CSV en un DataFrame de pandas
ARGOS = pd.read_csv(archivo_csv, sep=';')
ARGOS.info()
print(ARGOS)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3401 entries, 0 to 3400
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Fecha 3401 non-null object
1 Último 3401 non-null object
2 Apertura 3401 non-null object
3 Máximo 3401 non-null object
4 Mínimo 3401 non-null object
5 Vol. 3401 non-null object
6 % var. 3401 non-null object
dtypes: object(7)
memory usage: 186.1+ KB
Fecha Último Apertura Máximo Mínimo Vol. % var.
0 28/02/2024 13.840,00 13.360,00 13.840,00 13.360,00 173,30K 2,37%
1 27/02/2024 13.520,00 13.600,00 13.600,00 13.480,00 85,25K 0,00%
2 26/02/2024 13.520,00 13.280,00 13.560,00 13.280,00 53,98K -0,44%
3 25/02/2024 13.580,00 13.020,00 13.600,00 13.000,00 397,70K 2,41%
4 24/02/2024 13.260,00 13.000,00 13.260,00 13.000,00 51,67K 2,31%
... ... ... ... ... ... ... ...
3396 11/11/2014 18.800,00 19.000,00 19.000,00 18.640,00 449,45K -0,95%
3397 10/11/2014 18.980,00 19.500,00 19.500,00 18.980,00 704,07K -3,16%
3398 09/11/2014 19.600,00 19.800,00 19.800,00 19.600,00 901,59K -1,90%
3399 08/11/2014 19.980,00 19.960,00 20.000,00 19.880,00 124,71K 0,00%
3400 07/11/2014 19.980,00 19.900,00 19.980,00 19.880,00 59,52K 0,00%
[3401 rows x 7 columns]
# Convertir la columna de fecha al formato de fecha
ARGOS['Fecha'] = pd.to_datetime(ARGOS['Fecha'], format='%d/%m/%Y')
# Convertir las comas en los puntos en las columnas numéricas
columnas_numericas = ['Último', 'Apertura', 'Máximo', 'Mínimo']
# Eliminar los puntos de los números antes de convertirlos a float
ARGOS[columnas_numericas] = ARGOS[columnas_numericas].replace('\,', '.', regex=True)
ARGOS[columnas_numericas] = ARGOS[columnas_numericas].replace('\.', '', regex=True)
# Convertir las columnas numéricas al tipo float
ARGOS[columnas_numericas] = ARGOS[columnas_numericas].astype(float)
# Dividir entre 1000 para eliminar los ceros adicionales
ARGOS[columnas_numericas] = ARGOS[columnas_numericas].div(100000)
# Reordenar el DataFrame por fecha de la más antigua a la más reciente
ARGOS = ARGOS.sort_values(by='Fecha')
# Reiniciar el índice
ARGOS = ARGOS.reset_index(drop=True)
ARGOS.info()
print(ARGOS)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3401 entries, 0 to 3400
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Fecha 3401 non-null datetime64[ns]
1 Último 3401 non-null float64
2 Apertura 3401 non-null float64
3 Máximo 3401 non-null float64
4 Mínimo 3401 non-null float64
5 Vol. 3401 non-null object
6 % var. 3401 non-null object
dtypes: datetime64[ns](1), float64(4), object(2)
memory usage: 186.1+ KB
Fecha Último Apertura Máximo Mínimo Vol. % var.
0 2014-11-07 19.98 19.90 19.98 19.88 59,52K 0,00%
1 2014-11-08 19.98 19.96 20.00 19.88 124,71K 0,00%
2 2014-11-09 19.60 19.80 19.80 19.60 901,59K -1,90%
3 2014-11-10 18.98 19.50 19.50 18.98 704,07K -3,16%
4 2014-11-11 18.80 19.00 19.00 18.64 449,45K -0,95%
... ... ... ... ... ... ... ...
3396 2024-02-24 13.26 13.00 13.26 13.00 51,67K 2,31%
3397 2024-02-25 13.58 13.02 13.60 13.00 397,70K 2,41%
3398 2024-02-26 13.52 13.28 13.56 13.28 53,98K -0,44%
3399 2024-02-27 13.52 13.60 13.60 13.48 85,25K 0,00%
3400 2024-02-28 13.84 13.36 13.84 13.36 173,30K 2,37%
[3401 rows x 7 columns]
Hasta este punto solo hemos preparado nuestros datos, asegurandonos que las variables tuvieran el tipo correcto de dato, y para una exploracion más sencilla la conversion o el reescalado de las variables numericas que respresentan un valor de la accion, las cuales son: Último, Apertura, Máximo y Mínimo, este reescalado mencionado consiste en eliminar los miles "000", es decir 3 ceros, de los valores obtenidos.
A continuacion nos disponemos a revisar como se verian las series de estas variables.
import plotly.graph_objects as go
# Crear una figura de plotly
fig = go.Figure()
# Agregar cada línea al gráfico
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Apertura'], mode='lines', name='Apertura'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Último'], mode='lines', name='Último'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Máximo'], mode='lines', name='Máximo'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Mínimo'], mode='lines', name='Mínimo'))
# Actualizar el diseño del botón
fig.update_layout(
updatemenus=[
dict(
buttons=list([
dict(label="Apertura",
method="update",
args=[{"visible": [True, False, False, False]},
{"title": "Serie de tiempo variable Apertura"}]),
dict(label="Último",
method="update",
args=[{"visible": [False, True, False, False]},
{"title": "Serie de tiempo variable Último"}]),
dict(label="Máximo",
method="update",
args=[{"visible": [False, False, True, False]},
{"title": "Serie de tiempo variable Máximo"}]),
dict(label="Mínimo",
method="update",
args=[{"visible": [False, False, False, True]},
{"title": "Serie de tiempo variable Mínimo"}])
]),
direction="down",
pad={"r": 10, "t": 10},
showactive=True,
x=0.05,
xanchor="left",
y=1.15,
yanchor="top"
),
]
)
# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', rangeslider_visible=True)
# Actualizar el diseño del eje y
fig.update_yaxes(title_text='Valor')
# Actualizar el título del gráfico
fig.update_layout(title='Series de tiempo de variables ARGOS')
# Mostrar el gráfico
fig.show()
Del gafico anterio podemos conlcuir que todas las variables se comportan de manera similar en el tiempo explorado, por lo cual la eleccion de la variable en la que nos centraremos no tendra una influencia positiva o negativa en nuestro estudio, sin embargo podemos notar que entre el 2021 y 2022 hubo una caida muy brusca del precio de las acciones del grupo ARGOS lo cual si podra afectar de manera directa los resultados que obtengamos.
Recomendacion: Tratar de realizar la exploracion de la serie antes de la caida y comparar resultados
ELECCION DE LA VARIABLE Y DESARROLLO DE METODOLOGIAS
En la parte anterior del codigo pudimos ver como todas las variables poseen un comportamiento bastante parecido, lo cual tiene sentido en el ambito en el cual nos encontramos, dado que estamos hablando del precio de las acciones de una compañia y este suele comportarce de forma muy similar hablando en terminos de las variables del precio de la apertura, el precio maximo y minimo o el cierre.
Por esto hemos decidido que la variable elegida para desarrollar el proyecto sera la Apertura o mejor dicho el precio de la apertura diaria del valor de la accion en la bolsa para el Grupo Argos, en miles de pesos Colombianos. Teniendo esto en cuenta, tambien podríamos aplicar el siguiente desarrollo a las otras variables pero eso no sera tema principal en este documento.
# Seleccionar las columnas 'Fecha' y 'Apertura' del DataFrame ARGOS
Serie = ARGOS[['Fecha', 'Apertura']]
# Visualizar las primeras filas de la serie
print(Serie.head())
# Resumen estadístico de la serie
print(Serie.describe())
Fecha Apertura
0 2014-11-07 19.90
1 2014-11-08 19.96
2 2014-11-09 19.80
3 2014-11-10 19.50
4 2014-11-11 19.00
Fecha Apertura
count 3401 3401.000000
mean 2019-07-03 23:59:59.999999744 16.919274
min 2014-11-07 00:00:00 7.100000
25% 2017-03-06 00:00:00 13.930000
50% 2019-07-04 00:00:00 17.980000
75% 2021-10-31 00:00:00 19.720000
max 2024-02-28 00:00:00 24.400000
std NaN 3.987770
# Crear una serie de tiempo con Pandas Time Series (ts)
Apertura = pd.Series(Serie['Apertura'].values, index=Serie['Fecha'])
import plotly.graph_objects as go
import pandas as pd
# Crear una serie de tiempo con Pandas Time Series (ts)
Apertura = pd.Series(Serie['Apertura'].values, index=Serie['Fecha'])
# Crear la figura de Plotly
fig = go.Figure()
# Agregar la serie de tiempo al gráfico
fig.add_trace(go.Scatter(x=Apertura.index, y=Apertura.values, mode='lines'))
# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', rangeslider_visible=True)
# Actualizar el diseño del eje y
fig.update_yaxes(title_text='Valor de Apertura')
# Actualizar el título del gráfico
fig.update_layout(title='Serie de tiempo OPEN')
# Mostrar el gráfico
fig.show()
TRANSFORMACION DE BOX-COX PARA REDUCCION DE LA VARIANZA
import numpy as np
from scipy import stats
from scipy.stats import boxcox
import matplotlib.pyplot as plt
# Calcular el lambda óptimo para la transformación de Box-Cox
fitted_data, fitted_lambda = stats.boxcox(ARGOS['Apertura'])
print("Lambda óptimo para Box-Cox:", fitted_lambda)
# Aplicar la transformación de Box-Cox a la serie de tiempo de Apertura
serie_boxcox = boxcox(Apertura, lmbda=fitted_lambda)
print(serie_boxcox)
Lambda óptimo para Box-Cox: 2.1723466235235915 [304.77160462 306.77434326 301.44940865 ... 126.3184058 133.04859268 127.9833468 ]
# Crear una figura de plotly
fig = go.Figure()
# Agregar cada línea al gráfico
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=ARGOS['Apertura'], mode='lines', name='Serie de tiempo Apertura'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=serie_boxcox, mode='lines', name='Serie de tiempo Apertura-BoxCox', visible=False))
# Actualizar el diseño del botón
fig.update_layout(
updatemenus=[
dict(
buttons=list([
dict(label="Serie de tiempo Apertura",
method="update",
args=[{"visible": [True, False]},
{"title": "Serie de tiempo Apertura"}]),
dict(label="Serie de tiempo Apertura-BoxCox",
method="update",
args=[{"visible": [False, True]},
{"title": "Serie de tiempo Apertura-BoxCox"}])
]),
direction="down",
pad={"r": 10, "t": 10},
showactive=True,
x=0.05,
xanchor="left",
y=1.15,
yanchor="top"
),
]
)
# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', rangeslider_visible=True)
# Actualizar el diseño del eje y
fig.update_yaxes(title_text='Valor')
# Actualizar el título del gráfico
fig.update_layout(title='Comparación de series de tiempo de Apertura')
# Mostrar el gráfico
fig.show()
TRANSFORMACION LOGARITMICA
# Calcular el lambda óptimo para la transformación logarítmica
optimal_lambda_log = np.argmax(np.abs(np.diff(np.log(Apertura))))
print("Lambda óptimo para transformación logarítmica:", optimal_lambda_log)
# Aplicar la transformación logarítmica a la serie de tiempo de Apertura
serie_log_apertura = np.log(Apertura)
Lambda óptimo para transformación logarítmica: 2477
# Crear una figura de plotly
fig = go.Figure()
# Agregar cada línea al gráfico
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=serie_log_apertura, mode='lines', name='Serie de tiempo Log-Apertura'))
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=Apertura, mode='lines', name='Serie de tiempo Apertura', visible=False))
# Actualizar el diseño del botón
fig.update_layout(
updatemenus=[
dict(
buttons=list([
dict(label="Serie de tiempo Log-Apertura",
method="update",
args=[{"visible": [True, False]},
{"title": "Serie de tiempo Log-Apertura"}]),
dict(label="Serie de tiempo Apertura",
method="update",
args=[{"visible": [False, True]},
{"title": "Serie de tiempo Apertura"}])
]),
direction="down",
pad={"r": 10, "t": 10},
showactive=True,
x=0.05,
xanchor="left",
y=1.15,
yanchor="top"
),
]
)
# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', rangeslider_visible=True)
# Actualizar el diseño del eje y
fig.update_yaxes(title_text='Valor')
# Actualizar el título del gráfico
fig.update_layout(title='Comparación de series de tiempo de Log-Apertura')
# Mostrar el gráfico
fig.show()
A partir de este punto intentaremos mostrar los resultados para ambas series teniendo en cuenta los datos en su escala original y los datos en escala log, esto con la intencion de tener una comparacion más directa sobre lo que puede causar la tranformacion de los datos en los resultados de nuestro ejercicio.
ESTIMACION Y ELIMINACION DE LA TENDENCIA
import statsmodels.api as sm
# Estimación de la tendencia utilizando lm (regresión lineal) para datos originales
X_original = sm.add_constant(np.arange(len(ARGOS["Apertura"]))) # Añadir una columna de unos para intercepto
fit_Apertura_original = sm.OLS(ARGOS["Apertura"], X_original).fit()
# Imprimir resumen del modelo para datos originales
print(fit_Apertura_original.summary())
OLS Regression Results
==============================================================================
Dep. Variable: Apertura R-squared: 0.537
Model: OLS Adj. R-squared: 0.537
Method: Least Squares F-statistic: 3938.
Date: Sun, 07 Apr 2024 Prob (F-statistic): 0.00
Time: 19:19:31 Log-Likelihood: -8221.3
No. Observations: 3401 AIC: 1.645e+04
Df Residuals: 3399 BIC: 1.646e+04
Df Model: 1
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 21.9772 0.093 236.116 0.000 21.795 22.160
x1 -0.0030 4.74e-05 -62.752 0.000 -0.003 -0.003
==============================================================================
Omnibus: 2345.746 Durbin-Watson: 0.014
Prob(Omnibus): 0.000 Jarque-Bera (JB): 196.750
Skew: 0.026 Prob(JB): 1.89e-43
Kurtosis: 1.823 Cond. No. 3.93e+03
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 3.93e+03. This might indicate that there are
strong multicollinearity or other numerical problems.
# Modelo en escala log para los datos en escala logarítmica
log_original_data = np.log(ARGOS["Apertura"])
X_log = sm.add_constant(np.arange(len(log_original_data))) # Añadir una columna de unos para intercepto
fit_logApertura_log = sm.OLS(log_original_data, X_log).fit()
# Imprimir resumen del modelo en escala log para los datos en escala logarítmica
print(fit_logApertura_log.summary())
OLS Regression Results
==============================================================================
Dep. Variable: Apertura R-squared: 0.540
Model: OLS Adj. R-squared: 0.540
Method: Least Squares F-statistic: 3995.
Date: Sun, 07 Apr 2024 Prob (F-statistic): 0.00
Time: 19:19:34 Log-Likelihood: 952.38
No. Observations: 3401 AIC: -1901.
Df Residuals: 3399 BIC: -1888.
Df Model: 1
Covariance Type: nonrobust
==============================================================================
coef std err t P>|t| [0.025 0.975]
------------------------------------------------------------------------------
const 3.1386 0.006 500.416 0.000 3.126 3.151
x1 -0.0002 3.19e-06 -63.205 0.000 -0.000 -0.000
==============================================================================
Omnibus: 538.805 Durbin-Watson: 0.014
Prob(Omnibus): 0.000 Jarque-Bera (JB): 149.447
Skew: -0.227 Prob(JB): 3.53e-33
Kurtosis: 2.079 Cond. No. 3.93e+03
==============================================================================
Notes:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 3.93e+03. This might indicate that there are
strong multicollinearity or other numerical problems.
"RESULTADOS DE LOS MODELOS PARA AMBAS SERIES"
original_data = ARGOS["Apertura"]
import plotly.subplots as sp
import plotly.graph_objects as go
# Crear subgráficos con make_subplots
fig = sp.make_subplots(rows=1, cols=2, subplot_titles=('Serie original con ajuste de tendencia', 'Serie en escala logarítmica con ajuste de tendencia'))
# Agregar trazas al primer panel
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=original_data, mode='lines', name='Serie original', line=dict(color='blue')), row=1, col=1)
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=fit_Apertura_original.fittedvalues, mode='lines', name='Ajuste de tendencia', line=dict(color='red')), row=1, col=1)
# Agregar trazas al segundo panel
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=log_original_data, mode='lines', name='Serie en escala logarítmica', line=dict(color='blue')), row=1, col=2)
fig.add_trace(go.Scatter(x=ARGOS['Fecha'], y=fit_logApertura_log.fittedvalues, mode='lines', name='Ajuste de tendencia', line=dict(color='red')), row=1, col=2)
# Actualizar el diseño del eje x
fig.update_xaxes(title_text='Fecha', row=1, col=1)
fig.update_xaxes(title_text='Fecha', row=1, col=2)
# Actualizar el diseño del eje y para el primer panel
fig.update_yaxes(title_text='Valor en escala original', row=1, col=1)
# Actualizar el diseño del eje y para el segundo panel
fig.update_yaxes(title_text='Valor en escala log', row=1, col=2)
# Mostrar el gráfico
fig.show()
# Eliminamos la tendencia de la serie original
Apertura_sin_tendencia = original_data - fit_Apertura_original.fittedvalues
# Eliminamos la tendencia de la serie en escala logarítmica
logApertura_sin_tendencia = log_original_data - fit_logApertura_log.fittedvalues
import plotly.subplots as sp
import plotly.graph_objects as go
import pandas as pd
import statsmodels.api as sm
# Calcular autocorrelaciones para la serie en escala original
autocorrelation_original = sm.tsa.acf(Apertura_sin_tendencia, nlags=len(Apertura_sin_tendencia)-1)
# Crear una figura de Plotly para la serie en escala original
fig_original = go.Figure()
# Agregar la serie en escala original
fig_original.add_trace(go.Scatter(x=ARGOS['Fecha'], y=Apertura_sin_tendencia, mode='lines', name='Serie en escala original', line=dict(color='blue')))
# Actualizar el diseño del eje x y y
fig_original.update_xaxes(title_text='Fecha')
fig_original.update_yaxes(title_text='Valor en escala original')
# Mostrar la serie en escala original
fig_original.show()
# Crear una figura de Plotly para el autocorrelograma en escala original
fig_autocorrelation_original = go.Figure()
# Agregar el autocorrelograma en escala original
fig_autocorrelation_original.add_trace(go.Bar(x=list(range(len(Apertura_sin_tendencia))), y=autocorrelation_original, name='Autocorrelograma en escala original', marker=dict(color='blue')))
# Actualizar el diseño del eje x y y
fig_autocorrelation_original.update_xaxes(title_text='Lags')
fig_autocorrelation_original.update_yaxes(title_text='Autocorrelación')
# Agregar Range Slider para seleccionar un rango de lags
fig_autocorrelation_original.update_layout(
xaxis=dict(title='Lags', rangeslider=dict(visible=True), type='linear')
)
# Mostrar el autocorrelograma en escala original
fig_autocorrelation_original.show()
import plotly.graph_objects as go
import statsmodels.api as sm
# Calcular autocorrelaciones para la serie en escala logarítmica
autocorrelation_log = sm.tsa.acf(logApertura_sin_tendencia, nlags=len(logApertura_sin_tendencia)-1)
# Crear una figura de Plotly para la serie en escala logarítmica
fig_log = go.Figure()
# Agregar la serie en escala logarítmica
fig_log.add_trace(go.Scatter(x=ARGOS['Fecha'], y=logApertura_sin_tendencia, mode='lines', name='Serie en escala logarítmica', line=dict(color='blue')))
# Actualizar el diseño del eje x y y
fig_log.update_xaxes(title_text='Fecha')
fig_log.update_yaxes(title_text='Valor en escala logarítmica')
# Mostrar la serie en escala logarítmica
fig_log.show()
# Crear una figura de Plotly para el autocorrelograma en escala logarítmica
fig_autocorrelation_log = go.Figure()
# Agregar el autocorrelograma en escala logarítmica
fig_autocorrelation_log.add_trace(go.Bar(x=list(range(len(logApertura_sin_tendencia))), y=autocorrelation_log, name='Autocorrelograma en escala logarítmica', marker=dict(color='blue')))
# Actualizar el diseño del eje x y y
fig_autocorrelation_log.update_xaxes(title_text='Lags')
fig_autocorrelation_log.update_yaxes(title_text='Autocorrelación')
# Agregar Range Slider para seleccionar un rango de lags
fig_autocorrelation_log.update_layout(
xaxis=dict(title='Lags', rangeslider=dict(visible=True), type='linear')
)
# Mostrar el autocorrelograma en escala logarítmica
fig_autocorrelation_log.show()
DESCOMPOSICION DE LAS SERIES
ESCALA ORIGINAL
import pandas as pd
import plotly.graph_objects as go
from statsmodels.tsa.seasonal import seasonal_decompose
# Descomposición estacional utilizando seasonal_decompose
result = seasonal_decompose(ARGOS['Apertura'], model='additive', period=13) # Ajusta el período según sea necesario
# Crear una figura de Plotly para la descomposición estacional
fig = go.Figure()
# Agregar la serie original a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=ARGOS['Apertura'], mode='lines', name='Serie Original', visible=True))
# Configurar títulos y etiquetas de ejes
titles = ['Serie Original', 'Tendencia', 'Estacionalidad', 'Residual']
y_labels = ['Valor', 'Tendencia', 'Estacionalidad', 'Residual']
# Crear botones para cambiar entre los gráficos
buttons = []
for i, title in enumerate(titles):
visibility = [False] * len(titles)
visibility[i] = True
button = dict(label=title,
method="update",
args=[{"visible": visibility},
{"title": title,
"yaxis": {"title": {"text": y_labels[i]}}}],
)
buttons.append(button)
# Agregar la tendencia a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.trend, mode='lines', name='Tendencia', visible=False))
# Agregar la estacionalidad a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.seasonal, mode='lines', name='Estacionalidad', visible=False))
# Agregar el residuo a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.resid, mode='lines', name='Residual', visible=False))
# Agregar botones al layout
fig.update_layout(
updatemenus=[
{
"buttons": buttons,
"direction": "down",
"showactive": True,
"x": 0.5,
"xanchor": "center",
"y": 1.15,
"yanchor": "top"
}
]
)
# Mostrar la figura
fig.show()
ESCALA LOG
import pandas as pd
import plotly.graph_objects as go
from statsmodels.tsa.seasonal import seasonal_decompose
# Descomposición estacional utilizando seasonal_decompose
result = seasonal_decompose(np.log(ARGOS['Apertura']), model='additive', period=13) # Ajusta el período según sea necesario
# Crear una figura de Plotly para la descomposición estacional
fig = go.Figure()
# Agregar la serie original en escala logarítmica a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=np.log(ARGOS['Apertura']), mode='lines', name='Serie Original', visible=True))
# Configurar títulos y etiquetas de ejes
titles = ['Serie Original', 'Tendencia', 'Estacionalidad', 'Residual']
y_labels = ['Valor', 'Tendencia', 'Estacionalidad', 'Residual']
# Crear botones para cambiar entre los gráficos
buttons = []
for i, title in enumerate(titles):
visibility = [False] * len(titles)
visibility[i] = True
button = dict(label=title,
method="update",
args=[{"visible": visibility},
{"title": title,
"yaxis": {"title": {"text": y_labels[i]}}}],
)
buttons.append(button)
# Agregar la tendencia a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.trend, mode='lines', name='Tendencia', visible=False))
# Agregar la estacionalidad a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.seasonal, mode='lines', name='Estacionalidad', visible=False))
# Agregar el residuo a la figura
fig.add_trace(go.Scatter(x=ARGOS.index, y=result.resid, mode='lines', name='Residual', visible=False))
# Agregar botones al layout
fig.update_layout(
updatemenus=[
{
"buttons": buttons,
"direction": "down",
"showactive": True,
"x": 0.5,
"xanchor": "center",
"y": 1.15,
"yanchor": "top"
}
]
)
# Mostrar la figura
fig.show()
DIFERENCIA ORDINARA
import pandas as pd
import numpy as np
import plotly.graph_objects as go
# Diferencia ordinaria de la serie original
diff_serie = ARGOS['Apertura'].diff(periods=1)
# Diferencia ordinaria de la serie en escala logarítmica
diff_lserie = np.diff(np.log(ARGOS['Apertura']))
# Crear una figura de Plotly para las diferencias ordinarias
fig = go.Figure()
# Agregar la diferencia ordinaria de la serie original a la figura
fig.add_trace(go.Scatter(x=ARGOS.index[1:], y=diff_serie, mode='lines', name='Diferencia Ordinaria Serie Original', visible=True))
# Agregar la diferencia ordinaria de la serie en escala logarítmica a la figura
fig.add_trace(go.Scatter(x=ARGOS.index[1:], y=diff_lserie, mode='lines', name='Diferencia Ordinaria Serie en Escala Logarítmica', visible=False))
# Configurar título y etiquetas de ejes
fig.update_layout(title='Diferencia Ordinaria de la Serie Original y en Escala Logarítmica',
xaxis_title='Tiempo',
yaxis_title='Diferencia')
# Configurar botón para cambiar entre las diferencias ordinarias
fig.update_layout(
updatemenus=[
{
"buttons": [
{
"args": [{"visible": [True, False]}, {"title": "Diferencia Ordinaria Serie Original"}],
"label": "Serie Original",
"method": "update"
},
{
"args": [{"visible": [False, True]}, {"title": "Diferencia Ordinaria Serie en Escala Logarítmica"}],
"label": "Serie en Escala Log",
"method": "update"
}
],
"direction": "down",
"showactive": True,
"x": 0.5,
"xanchor": "center",
"y": 1.15,
"yanchor": "top"
}
]
)
# Mostrar la figura
fig.show()
RELACIONES NO LINEALES USANDO LA DISPERSION
ESCALA ORIGINAL
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Crear una figura con subtramas para mostrar todas las gráficas en una cuadrícula
fig = make_subplots(rows=4, cols=3, subplot_titles=[f'Relaciones t y t+{i}' for i in range(1, 13)],
horizontal_spacing=0.1, vertical_spacing=0.1)
# Añadir cada relación no lineal de dispersión a la figura
for i in range(1, 13):
row = (i - 1) // 3 + 1
col = (i - 1) % 3 + 1
scatter = go.Scatter(x=diff_serie[:-i], y=diff_serie.shift(-i)[:-i], mode='markers', name=f'Relaciones t y t+{i}')
fig.add_trace(scatter, row=row, col=col)
# Configurar título y etiquetas de ejes
fig.update_layout(title='Relaciones No Lineales de Dispersión',
xaxis_title='Apertura(t)',
yaxis_title='Apertura(t + i)',
height=720, width=1080) # Ajustar el tamaño de la figura
# Mostrar la figura
fig.show()
ESCALA LOG
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Convertir la serie en escala logarítmica a un objeto de Pandas Series
diff_lserie = pd.Series(diff_lserie)
# Crear una figura con subtramas para mostrar todas las gráficas en una cuadrícula
fig = make_subplots(rows=4, cols=3, subplot_titles=[f'Relaciones t y t+{i}' for i in range(1, 13)],
horizontal_spacing=0.1, vertical_spacing=0.1)
# Añadir cada relación no lineal de dispersión a la figura
for i in range(1, 13):
row = (i - 1) // 3 + 1
col = (i - 1) % 3 + 1
scatter = go.Scatter(x=diff_lserie[:-i], y=diff_lserie.shift(-i)[:-i], mode='markers', name=f'Relaciones t y t+{i}')
fig.add_trace(scatter, row=row, col=col)
# Configurar título y etiquetas de ejes
fig.update_layout(title='Relaciones No Lineales de Dispersión - Serie en Escala Logarítmica',
xaxis_title='Apertura(t)',
yaxis_title='Apertura(t + i)',
height=720, width=1080) # Ajustar el tamaño de la figura
# Mostrar la figura
fig.show()
ANALISIS DE AUTOCORRELACION Y AUTOCORRELACION PARCIAL
ESCALA ORIGINAL
import plotly.graph_objects as go
from statsmodels.tsa.stattools import acf, pacf
import numpy as np
# Calcular ACF y PACF
acf_values, acf_confint = acf(diff_serie, nlags=100, fft=True, alpha=0.1)
# Gráfico de ACF
fig_acf = go.Figure()
fig_acf.add_trace(go.Bar(x=list(range(1, 100)), y=acf_values[1:], error_y=dict(type='data', array=acf_confint[1:, 1]-acf_values[1:])))
fig_acf.update_layout(title="Serie diferenciada de costos - ACF", xaxis_title="Lag", yaxis_title="Autocorrelación")
fig_acf.show()
pacf_values, pacf_confint = pacf(diff_serie, nlags=100, alpha=0.1)
# Gráfico de PACF
fig_pacf = go.Figure()
fig_pacf.add_trace(go.Bar(x=list(range(1, 100)), y=pacf_values[1:], error_y=dict(type='data', array=pacf_confint[1:, 1]-pacf_values[1:])))
fig_pacf.update_layout(title="Serie diferenciada de costos - PACF", xaxis_title="Lag", yaxis_title="Autocorrelación parcial")
fig_pacf.show()
No se observan los graficos de Autocorrelacion y Autocorrelacion parcial para la serie diferenciadad con los datos en la escala original, esto significa algo?
ESCALA LOG
import plotly.graph_objects as go
from statsmodels.tsa.stattools import acf, pacf
# Calcular ACF y PACF
acf_values_log, acf_confint_log = acf(diff_lserie, nlags=100, fft=True, alpha=0.05)
pacf_values_log, pacf_confint_log = pacf(diff_lserie, nlags=100, alpha=0.05)
# Gráfico de ACF
fig_acf_log = go.Figure()
fig_acf_log.add_trace(go.Bar(x=list(range(1, 100)), y=acf_values_log[1:], error_y=dict(type='data', array=acf_confint_log[1:, 1]-acf_values_log[1:])))
fig_acf_log.update_layout(title="Serie diferenciada y con logaritmo de costos - ACF", xaxis_title="Lag", yaxis_title="Autocorrelación")
fig_acf_log.show()
# Gráfico de PACF
fig_pacf_log = go.Figure()
fig_pacf_log.add_trace(go.Bar(x=list(range(1, 100)), y=pacf_values_log[1:], error_y=dict(type='data', array=pacf_confint_log[1:, 1]-pacf_values_log[1:])))
fig_pacf_log.update_layout(title="Serie diferenciada y con logaritmo de costos - PACF", xaxis_title="Lag", yaxis_title="Autocorrelación parcial")
fig_pacf_log.show()
INDICE DE INFORMACION MUTUA
Indice de informacion mutua tambien contrasta varias de los rezagos, vas por buen camino
ESCALA ORIGINAL
#pip install pyinform
import numpy as np
import plotly.graph_objects as go
# Función para plotear el gráfico de Lag Plot para un lag específico
def lag_plot(x, lag=1):
x_lagged = x[:-lag]
x_shifted = x[lag:]
fig = go.Figure()
fig.add_trace(go.Scatter(x=x_lagged, y=x_shifted, mode='markers', marker=dict(size=5)))
corr_value = np.corrcoef(x_lagged, x_shifted)[0, 1]
fig.add_annotation(text=f'Correlation: {corr_value:.2f}', x=x.max() * 0.9, y=x.min() * 0.9, showarrow=False)
fig.update_layout(title=f"Lag Plot - Lag {lag}", xaxis_title="Lag(t)", yaxis_title=f"Lag(t + {lag})")
fig.show()
# Agregar botones para cada gráfico de Lag Plot
buttons = []
for lag in range(1, 13):
button = dict(label=f"Lag {lag}",
method="update",
args=[{"visible": [False] * (lag - 1) + [True] + [False] * (12 - lag)},
{"title": f"Lag Plot - Lag {lag}"}])
buttons.append(button)
# Configurar la figura con los gráficos de Lag Plot
fig = go.Figure()
for lag in range(1, 13):
x = ARGOS['Apertura']
x_lagged = x[:-lag]
x_shifted = x[lag:]
fig.add_trace(go.Scatter(x=x_lagged, y=x_shifted, mode='markers', marker=dict(size=5), visible=False))
# Agregar el primer botón activado por defecto
fig.update_layout(updatemenus=[{"active": 0, "buttons": buttons}])
# Configurar diseño y mostrar figura
fig.update_layout(title="Lag Plots - Lag 1", xaxis_title="Lag(t)", yaxis_title="Lag(t + lag)")
fig.show()
import numpy as np
import plotly.graph_objects as go
import pyinform
# Calcular el índice de información mutua para los primeros 12 lags de Apertura
max_lag = 50
lags = list(range(1, max_lag+1))
ami_apertura = [pyinform.mutualinfo.mutual_info(np.array(ARGOS['Apertura'][i:]), np.array(ARGOS['Apertura'][:-i])) for i in lags]
# Gráfico del Índice de Información Mutua para los primeros 12 lags de Apertura
fig_ami = go.Figure()
fig_ami.add_trace(go.Scatter(x=lags, y=ami_apertura, mode='lines', name='Mutual Information'))
fig_ami.update_layout(title="Índice de Información Mutua (Lags 1-12) - Apertura", xaxis_title="Lag", yaxis_title="Mutual Information (Bits)")
fig_ami.show()
ESCALA LOG
import plotly.graph_objects as go
import numpy as np
import pyinform
# Función para plotear el gráfico de Lag Plot para un lag específico
def lag_plot(x, lag=1):
x_lagged = x[:-lag]
x_shifted = x[lag:]
fig = go.Figure()
fig.add_trace(go.Scatter(x=x_lagged, y=x_shifted, mode='markers', marker=dict(size=5)))
corr_value = np.corrcoef(x_lagged, x_shifted)[0, 1]
fig.add_annotation(text=f'Correlation: {corr_value:.2f}', x=x.max() * 0.9, y=x.min() * 0.9, showarrow=False)
fig.update_layout(title=f"Lag Plot - Lag {lag}", xaxis_title="Lag(t)", yaxis_title=f"Lag(t + {lag})")
fig.show()
# Crear una lista de botones para seleccionar cada gráfico de Lag Plot individualmente
buttons = []
for lag in range(1, 13):
button = dict(label=f"Lag {lag}",
method="update",
args=[{"visible": [False] * (lag - 1) + [True] + [False] * (12 - lag)},
{"title": f"Lag Plot - Lag {lag}"}])
buttons.append(button)
# Configurar la figura con los gráficos de Lag Plot
fig = go.Figure()
for lag in range(1, 13):
x = np.log(ARGOS['Apertura'])
x_lagged = x[:-lag]
x_shifted = x[lag:]
fig.add_trace(go.Scatter(x=x_lagged, y=x_shifted, mode='markers', marker=dict(size=5), visible=False))
# Agregar el primer botón activado por defecto
fig.update_layout(updatemenus=[{"active": 0, "buttons": buttons}])
# Configurar diseño y mostrar figura
fig.update_layout(title="Lag Plots - Lag 1", xaxis_title="Lag(t)", yaxis_title="Lag(t + lag)")
fig.show()
# Calcular el índice de información mutua para la serie en escala logarítmica
lag_max = 50
ami_logapertura = [pyinform.mutualinfo.mutual_info(np.array(np.log(ARGOS['Apertura'][i:])), np.array(np.log(ARGOS['Apertura'][:-i]))) for i in range(1, lag_max+1)]
# Graficar el índice de información mutua
fig_ami = go.Figure()
fig_ami.add_trace(go.Scatter(x=list(range(1, lag_max+1)), y=ami_logapertura, mode='lines'))
fig_ami.update_layout(title="Índice de Información Mutua - logApertura", xaxis_title="Lag", yaxis_title="Mutual Information (Bits)")
fig_ami.show()
ESTACIONALIDAD DE LAS SUBSERIES
Monthplot lo que hace es tomar cada enero y compararlo con la informacion que se tiene de cada año para ese mes y aspi suceviamente, se muestra un grafico el cual corresponde 12 subgraficacos cada uno respresentando un mes y donde el eje x es el año (vas por buen camino solo faltan los otros meses)
import pandas as pd
import matplotlib.pyplot as plt
# Función para graficar subseries mensuales
def monthplot(series):
# Convertir el índice a un índice de fecha si aún no lo es
if not isinstance(series.index, pd.DatetimeIndex):
series.index = pd.to_datetime(series.index)
# Dividir la serie en subseries mensuales
subseries = [series[series.index.month == i] for i in range(1, 13)]
# Configurar la figura
fig, axes = plt.subplots(4, 3, figsize=(15, 10), sharex=True, sharey=True)
fig.suptitle('Explorando la estacionalidad subseries')
# Graficar cada subserie mensual
for i, ax in enumerate(axes.flatten()):
ax.plot(subseries[i])
ax.set_title(f'Mes {i+1}')
plt.tight_layout()
plt.show()
# Utilizar la función monthplot con tu serie de tiempo
monthplot(diff_serie)